package com.southwind.springboottest.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.southwind.springboottest.dao.BookDao;
import com.southwind.springboottest.entity.Book;
import com.southwind.springboottest.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.concurrent.TimeUnit;


@Service
public class BookServiceImpl implements BookService {

    @Autowired
    private BookDao bookDao;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;


    @Override
    public Book getById(Integer id) {

         Book book;
        String s = stringRedisTemplate.opsForValue().get(String.valueOf(id));
        if (!StringUtils.hasText(s)) {
            book = bookDao.selectById(id);
            //book不为null再执行下一步，为null则退出，解决缓存穿透（可使用布隆过滤器）
            String toJSONString = JSON.toJSONString(book);
            stringRedisTemplate.opsForValue().set(String.valueOf(id), toJSONString, 60, TimeUnit.SECONDS);//解决缓存雪崩
            return book;
        } else {
             book = JSON.parseObject(s, new TypeReference<Book>() {
            });
            return book;
        }
    }

    @Override
    public Page<Book> getall(Integer page, Integer size) {
        Page<Book> bookPage = new Page<>(page, size);
        return  bookDao.selectPage(bookPage, null);
        //List<Book> records = bookPage1.getRecords();

    }

    @Override
    public Integer addBook(Book newbook) {
        return bookDao.insert(newbook);
    }

    /**
     * 1、空结果缓存：解决缓存穿透(缓存和数据库中都没有所要数据) （布隆过滤器）
     * 2、设置过期时间（加随机值），解决缓存雪崩
     * 3、加锁，解决缓存击穿（缓存中没有所要数据，但DB中有所要数据，且此时有大量用户请求）
     *
     */
    //缓存存储格式：key：string
    //value: Json
    @Override
    public Book findById(Integer id) {
        Book book ;
        String s = stringRedisTemplate.opsForValue().get(String.valueOf(id));
        if (!StringUtils.hasText(s)) {
            book = bookDao.selectById(id);
            //book不为null再执行下一步，为null则退出，解决缓存穿透（或者布隆过滤器）
            if(book!=null){
                String toJSONString = JSON.toJSONString(book);
                stringRedisTemplate.opsForValue().set(String.valueOf(id), toJSONString, 60, TimeUnit.SECONDS);//解决缓存雪崩
                return book;
            }else {
                throw new RuntimeException("这个id不存在");
            }

        } else {
             book = JSON.parseObject(s, new TypeReference<Book>() {
            });
            return book;
        }

    }

    @Override
    public Integer updateById(Book book) {
        int i = bookDao.updateById(book);
        Book book1 = bookDao.selectById(book.getId());

        stringRedisTemplate.delete(String.valueOf(book1.getId()));//必须先把之前的缓存删除掉
        String s = JSON.toJSONString(book1);
        stringRedisTemplate.opsForValue().set(String.valueOf(book1.getId()), s, 60, TimeUnit.SECONDS);
        return i;
    }

    @Override
    public Integer deleteById(Integer id) {
        int i = bookDao.deleteById(id);
        stringRedisTemplate.delete(String.valueOf(id));//删除缓存
        return i;
    }


}
